#include "ScreenMirrorStream.h"
#include "mediaPriv.h"
#include "VideoDecode.h"
#include "airplay/AirplayDefaultSetting.h"
#include "customdisplay/DefaultSetting.h"
#include "VideoEncode.h"
#include "AudioEncode.h"
#include "AudioInMgr.h"
#include "UsbInStream.h"
#include "CurtainActManager.h"
#include "ConfigApi.h"
#include "WlanService.h"
#include "UsbAVStream.h"

#include "Pal/Net.h"
#include <vector>
#include <random>


/*------------------------------------------

1.若客户端重新设置流的通道--SetStream，则先比较新旧流的差异，确定流和编码通道是否要停止，调用stop停止流和解码通道，再调用start启动。

2.布局调整后是否要关闭未拼接通道的流待定。

=============================================*/
//#define MIRROR_BACK_ENABLE
#define BYOM_ENABLE

//#define TEST_FRAMERATE
//#define SAVE_OUTPUT_FILE
#ifdef SAVE_OUTPUT_FILE

static int fd = -1;
#define OUTPUT_FILE_NAME                "/tmp/recv.h264"
#endif


enum
{
    FULL_SCREEN = 0,
    PINP_SCREEN,
    MONTAGE_SCREEN    
}MirrorStyle;



#define NDK_CALLBACK 1

//#define RECORD_H264 1
#define                 MAX_FILE_NAME_LENGTH    255

#define DEVICE_1_ADDRESS  "192.168.16.117"
int device1Fd;

#define DEVICE_2_ADDRESS "192.168.17.118"
int device2Fd;

static pthread_t mirrorBackVideoThread;
static bool mirrorBackVideoRunning = false;

static pthread_t mirrorBackAudioThread;
static bool mirrorBackAudioRunning = false;

static bool dropFrameFlg_s = false;
static int iFrameNum_s = 0;
static VideoFormat mirrorVideoFormat_s = USBDISPLAY_VIDEO_FORMAT_H264;

static std::vector<std::string>                usbDispalyClientInfo_s;

static std::vector<std::string>                airpalyClientInfo_s;

static std::map<std::string, std::string>      usbDispalyMap_s;

static std::mutex 			                    clientInfoMutex_s;

static bool             dropAirplayFrameFlg_s = false;

static pthread_t        clientInfoUpdateThread_s;

static std::string      currentMirrorIp;


extern "C" int VIDEO_HdmioutControl(uint8_t cmd);

namespace Media{

using namespace std;

using namespace ConfigApi;

static void clientInfoUpdate(int clientType, char* clientIp)
{
    std::lock_guard<std::mutex> guard(clientInfoMutex_s);

    printf("usbDispalyClientInfo_s size=%d, airpalyClientInfo_s size=%d \n", usbDispalyClientInfo_s.size(), airpalyClientInfo_s.size());

    mirrorBackVideoRunning = false;
    mirrorBackAudioRunning = false;
    
    int ret = 0;

    for (vector<std::string>::iterator it = usbDispalyClientInfo_s.begin(); it != usbDispalyClientInfo_s.end(); it++) 
    {
		ret = UsbDisplayKickOut(ScreenMirrorStream::instance()->getContext(), (*it).c_str());
		if(ret != USBDISPLAY_ERROR_OK)
		{
            printf("UsbDisplayKickOut failed, client ip=%s\n", (*it).c_str()); 
            continue;
		}

		printf("UsbDisplayKickOut success, client ip=%s\n", (*it).c_str());
	}
	usbDispalyClientInfo_s.clear();

	for (vector<std::string>::iterator it = airpalyClientInfo_s.begin(); it != airpalyClientInfo_s.end(); it++) 
    {
		BZAirplayReceiverKickOutClient((*it).c_str());
        printf("BZAirplayReceiverKickOutClient success, client ip=%s\n", (*it).c_str());
	}
	airpalyClientInfo_s.clear();

    if(clientType == -1)
    {
        airpalyClientInfo_s.push_back(clientIp);
    }
    else
    {
	    usbDispalyClientInfo_s.push_back(clientIp);
	}
}


#if 1
static void onClientConnected(DeviceClient* client) {

    tracef("onClientConnected, client ip=%s, clientType=%d\n", client->ipAddress, client->clientType);
    ScreenMirrorStream::instance()->setUsbDisplayConnect(true);

#ifdef SAVE_OUTPUT_FILE
    if (fd == -1) {
        remove(OUTPUT_FILE_NAME);
        fd = open(OUTPUT_FILE_NAME, O_WRONLY | O_NONBLOCK | O_CREAT, 0644);
    }
#endif

}

static void onClientDisconnected(DeviceClient* client) {

#ifdef SAVE_OUTPUT_FILE
        if (fd != -1) {
            close(fd);
            fd = -1;
        }
#endif

    printf("onClientDisconnected, client ip=%s, , clientType=%d\n",  client->ipAddress, client->clientType);

    if(client->clientType == 1)
    {
        string mac;    
        if(usbDispalyMap_s.count(client->ipAddress) == 0)
        {
            Json::Value tailTable;
            IConfigInterface::GetInstance()->Get("Tail", tailTable);
        	mac = tailTable["mac"].asString();   
        }
        else
        {
            mac = usbDispalyMap_s[client->ipAddress];
        }

        printf("onClientDisconnected, mac=%s\n",mac.c_str());
     
        string ip =  client->ipAddress;
        bool res = WlanService::instance()->pingUtil("wlan1", ip);
        if(!res){
            WlanDisassociateSTA("wlan1", mac.c_str());
        }
    
    }

    if(clientInfoMutex_s.try_lock())
    {
        usbDispalyClientInfo_s.erase(remove(usbDispalyClientInfo_s.begin(), usbDispalyClientInfo_s.end(), client->ipAddress), usbDispalyClientInfo_s.end());

        if(usbDispalyClientInfo_s.size() == 0 && airpalyClientInfo_s.size() == 0
            && ScreenMirrorStream::instance()->getShareScreenStatus())
        {
            ScreenMirrorStream::instance()->streamLeaveDel();            
        }
        
        clientInfoMutex_s.unlock();
    }
}

static void onClientNameUpdated(DeviceClient* client) {
    printf("client name=%s\n", client->name);
}

static void onClientTypeUpdated(DeviceClient* client) {
    printf("onClientTypeUpdated, client=%s, type=%d\n", client->ipAddress, client->clientType);
}

static void onClientResolutionChanged(DeviceClient* client) {
    printf("onClientResolutionChanged, client=%s, w=%d, h=%d\n", client->ipAddress, client->resolution[0], client->resolution[1]);
}

void onDeviceUpdateTransmitterId(const char *ip, const char *transmitterId)
{
    printf("onDeviceUpdateTransmitterId ip=%s, transmitterId=%s\n", ip, transmitterId); //请求投屏的客户端信息

    std::string str = transmitterId;
    std::string key = ":";    
    str.insert(2 ,key);
    str.insert(5 ,key);
    str.insert(8 ,key);
    str.insert(11 ,key);
    str.insert(14 ,key);

    usbDispalyMap_s[ip] = str;
    //printf("onDeviceUpdateTransmitterId macAddr=%s\n", str.c_str()); 
}

static bool isPermitToShow(DeviceClient* client) {
    printf("isPermitToShow==>%s\n", client->ipAddress); //是否允许投屏在此控制

    clientInfoUpdate(client->clientType, client->ipAddress);
    return true;
}

static void onClientShow(DeviceClient* client) {
    printf("onClientShow==>%s,clientType=%d\n", client->ipAddress, client->clientType); //允许投屏的客户端信息
    
    ScreenMirrorStream::instance()->updateServerPassword();
    ScreenMirrorStream::instance()->setUsbDisplayConnect(false);

    dropFrameFlg_s = true;
    iFrameNum_s = 0;
    currentMirrorIp = client->ipAddress;

#if 0    
    int num = 0;
    CurtainActManager::instance()->getCurPlayNum(&num);

    if(num >= 200 && num < 204)
    {        
        ScreenMirrorStream::instance()->startSwitchTimer();         
    }
#endif

    ScreenMirrorStream::instance()->streamComeDel(client->clientType, client->ipAddress);
    
}

static void onClientHide(DeviceClient* client, UsbDisplayDeviceHideType type) {
    printf("onClientHide==>%s\n", client->ipAddress);

    mirrorBackVideoRunning = false; //onClientDisconnected回调比onClientHide慢很多
    mirrorBackAudioRunning = false;

    ScreenMirrorStream::instance()->streamLeaveDel();
}

#ifdef TEST_FRAMERATE 
unsigned long currentMillionSeconds() {
    struct timeval tp{};
    gettimeofday(&tp, nullptr);

    unsigned long now = tp.tv_sec * 1000 + tp.tv_usec / 1000;
    return now;
}

unsigned long lastPacketTime = 0;
unsigned long packetNums = 0;
unsigned long allPacketTimes = 0;
unsigned long allPacketNums = 0;
#endif
static void onVideoFrame(DeviceClient* client, char* buf, int length, int ts) {
    //printf("onVideoFrame==>%s, length=%d,ts=%d, frameh264Type=%d, frameh265Type=%d\n", client->ipAddress, length,ts, H264_TYPE(buf[4]), H265_TYPE(buf[4]) );

    if(currentMirrorIp != client->ipAddress || (length <= 0))
    {
		LOG_PrintWarn("ScreenMirrorStream::onVideoFrame currentMirrorIp:%s,ip=%s\n",currentMirrorIp.c_str(),client->ipAddress);
        return; //滤出干扰帧
    }
    
    static int frameCnt = 0;
    if(dropFrameFlg_s && (mirrorVideoFormat_s == USBDISPLAY_VIDEO_FORMAT_H264))
    {       
        if(length > 4)
        {
            int frameType = H264_TYPE(buf[4]);
            if(0x07 == frameType) //SPS
            {
                dropFrameFlg_s = false;
                LOG_PrintWarn("ScreenMirrorStream::onVideoFrame dropFrame done\n");
            }
            else
            {
                return;
            }
        }
        else
        {
            return;
        }
    }
    else if(dropFrameFlg_s && (mirrorVideoFormat_s == USBDISPLAY_VIDEO_FORMAT_H265))
    {       
        if(length > 4)
        {
            int frameType = H265_TYPE(buf[4]);
            if (0x20 == frameType && ++frameCnt > 1) //VPS/SPS/PPS/IDR合并发过来
            {
                dropFrameFlg_s = false;
                LOG_PrintWarn("ScreenMirrorStream::onVideoFrame dropFrame done,frameCnt=%d, length=%d\n", frameCnt, length);

                frameCnt = 0;
            }
            else
            {
                return;
            }
        }
        else
        {
            return;
        }
    }

#ifdef SAVE_OUTPUT_FILE
    write(fd, buf, length);
#endif

#ifdef TEST_FRAMERATE   
    unsigned long currentTime = currentMillionSeconds();
    if (lastPacketTime != 0 && currentTime - lastPacketTime > 10000){
        allPacketTimes++;

        //printf("1s中收到包数量为：%lu", packetNums);
        //printf("allPacketNums：%lu", allPacketNums);
        if (allPacketTimes != 0){
            printf("Average second receive video packetnum: %.1f \n", (float)allPacketNums / allPacketTimes / 10);
        }
        lastPacketTime = currentTime;
        packetNums=0;
    } else if (lastPacketTime == 0){
        lastPacketTime = currentTime;
    }
    packetNums++;
    allPacketNums++;
#endif 

    static uint64_t printCnt = 0;

#if 1

    StreamAbility ability = ScreenMirrorStream::instance()->getPlayAbility();
    if((ability == VIDEO_AUDIO) || (ability == VIDEO_ONLY))
    {
        ScreenMirrorStream::instance()->saveToCommQueue(buf, length, ts, 0);
    }
#endif

    if(printCnt++ % 320 == 0)
    {
        LOG_PrintWarn("ScreenMirrorStream::onVideoFrame receive success,length=%d\n", length);
        printCnt = 1;
    }

}

static void onAudioFrame(DeviceClient* client, char* buf, int length, int ts) {
    StreamAbility ability = ScreenMirrorStream::instance()->getPlayAbility();
    if((ability == VIDEO_AUDIO) || (ability == AUDIO_ONLY))
    {
        ScreenMirrorStream::instance()->sendAudioPacket(buf, length, ts);

        //ScreenMirrorStream::instance()->saveToCommQueue(bar, length, ts, 1);
    }

    static uint64_t printCnt = 0;

    if(printCnt++ % 640 == 0)
    {
         LOG_PrintWarn("ScreenMirrorStream::onAudioFrame receive success, length=%d\n", length);
         printCnt = 1;
    }

}

static void onAudioInfoUpdated(DeviceClient* client, AudioInfo audioInfo) {
    //AUDIO_SAMPLE_RATE_48000 AUDIO_SAMPLE_RATE_44100
    printf("onAudioInfoUpdated:%s -->format=%d, sampleRate=%d,  channelCount=%d\n", client->ipAddress, audioInfo.format, audioInfo.rate, audioInfo.channelCount);

    AudioInAttr format = {0};
    format.enSampleFormat = SAMPLE_FMT_S16;               	
    format.enAiLayout = AI_NORMAL;
    format.source = EXTERNAL_IN_TYPE;
    if(audioInfo.rate == AUDIO_SAMPLE_RATE_48000){
        format.u32SampleRate = 48000;
    }else{
        format.u32SampleRate = 44100;
    }
    
    format.u32Channels = audioInfo.channelCount;
    format.u32NbSamples = 768;
    ScreenMirrorStream::instance()->setAudioFormat(format);
}

static void onUsbDeviceAttached123() {
    printf("onUsbDeviceAttached123\n");
}

static void onUsbDeviceDetached() {
    printf("onUsbDeviceDetached\n");

}

static void onUsbDeviceReady() {
    printf("onUsbDeviceReady\n");

}

static void onUsbDeviceGetVersionSuccess(const char* version) {
    printf("onUsbDeviceGetVersionSuccess:%s\n", version);

}

static void onUsbDeviceConfigureSuccess() {
    printf("onUsbDeviceConfigureSuccess\n");

}

static void onUsbDeviceUpgradeStarted() {
    printf("onUsbDeviceUpgradeStarted\n");

}

static void onUsbDeviceUpgradeInProgress(int progress) {
    printf("onUsbDeviceUpgradeInProgress\n");

}

static void onUsbDeviceUpgradeSuccess() {
    printf("onUsbDeviceUpgradeSuccess\n");

}

static void onUsbDeviceUpgradeFailed(UsbDisplayErrorCode code) {
    printf("onUsbDeviceUpgradeFailed\n");

}

static void onUsbDisplayLog(UsbDisplayLogLevel level, const char* msg) {
    printf("onUsbDisplayLog log:%s\n", msg);
}

static void* mirrorBackVideoThreadFun(void* arg) 
{
    pthread_detach(pthread_self()); // 此时状态改为 unjoinable,子线程住主动回收资源
     
    bool ret = false;
    auto* clientIp = (const char*) arg;

    SCREEN_vencPacket_t vencPacket = {0};
    
    uint64_t printCnt = 0;
    bool prinFlg = false;

    BYOMVideoInfo videoInfo = {0};
    videoInfo.format = 3 ;
    videoInfo.resolution = 2;
    videoInfo.fps = 30;
    uint64_t last_pts = 0;

    UsbDisplaySendByomVideoInfo(ScreenMirrorStream::instance()->getContext(), clientIp, videoInfo);

    tracef("mirrorBackVideoThreadFun enter\n");   

    while (mirrorBackVideoRunning)
    {
        memset(&vencPacket, 0, sizeof(vencPacket));

        ret = ScreenMirrorStream::instance()->VideoGetPacket(&vencPacket);
        if (!ret)
        {            
            usleep(3*1000); //todo
            continue;
        }
        if(last_pts == vencPacket.pts){
            warnf(" the frame is same of last frame , will lost it");
            ScreenMirrorStream::instance()->VideoReleasePacket();
            continue;
        }
        
        if(printCnt++ % 320 == 0)
        {
            tracef("UsbDisplaySendMirrorBackStream start\n");
            printCnt = 1;
            prinFlg = true;
        }

        last_pts = vencPacket.pts;
        if(mirrorBackVideoRunning && (vencPacket.dataLen > 0)) //发送之前增加判定
        {
        
        #ifdef MIRROR_BACK_ENABLE   
            UsbDisplaySendMirrorBackStream(ScreenMirrorStream::instance()->getContext(), clientIp, vencPacket.pBuf, vencPacket.dataLen, 0);
        #else
            
            int send_pts = vencPacket.pts % (int(2147483647));            
            UsbDisplaySendByomVideoData(ScreenMirrorStream::instance()->getContext(), clientIp, vencPacket.pBuf, vencPacket.dataLen, send_pts);            
        #endif
        }
    
        if(prinFlg)
        {
            LOG_PrintWarn("UsbDisplaySendMirrorBackStream succcess, video length=%u\n", vencPacket.dataLen);
            prinFlg = false;
        }

        ScreenMirrorStream::instance()->VideoReleasePacket();

        //media_FILE_Write2("wyg/mirroback.h264",vencPacket.pBuf, vencPacket.dataLen);
        
    } 

    tracef("mirrorBackVideoThreadFun leave\n");

    pthread_exit(nullptr);

    return NULL;

}


static void* mirrorBackAudioThreadFun(void* arg) 
{
    pthread_detach(pthread_self()); // 此时状态改为 unjoinable,子线程住主动回收资源
    
    bool ret;
    auto* clientIp = (const char*) arg;   
    char audioBuf[MAX_PCM_SIZE] = {0};
    int length = 0;
    uint64_t printCnt = 0;


    ByomAudioInfo audioInfo = {0};
    audioInfo.format = 1;
    audioInfo.sampleRate = AUDIO_SAMPLE_RATE_48000;
    audioInfo.channelCount = 1;   
    UsbDisplaySendByomAudioInfo(ScreenMirrorStream::instance()->getContext(), clientIp,audioInfo);

    tracef("mirrorBackAudioThreadFun enter\n");   

    while (mirrorBackAudioRunning)
    {
        memset(audioBuf, 0, sizeof(audioBuf));
        uint64_t pts = 0;
        ret = ScreenMirrorStream::instance()->AudioGetPacket(audioBuf, &length, pts);
        if (!ret)
        {
            usleep(1*1000); //todo
            continue;
        }

        int send_pts = pts % (int(2147483647));
        if(mirrorBackAudioRunning) //发送之前增加判定
        {
        #ifdef MIRROR_BACK_ENABLE    
            UsbDisplaySendMirrorBackAudioStream(ScreenMirrorStream::instance()->getContext(), clientIp, audioBuf, length, 0);

        #else
            UsbDisplaySendByomAudioData(ScreenMirrorStream::instance()->getContext(), clientIp, audioBuf, length, send_pts);

        #endif
        }
    
        if(printCnt++ % 640 == 0)
        {
            tracef("UsbDisplaySendMirrorBackAudioStream succcess, audio length=%d\n", length);
            printCnt = 1;
        }

        //media_FILE_Write2("wyg/mirrorback.pcm",audioBuf, length);
    }

    tracef("mirrorBackAudioThreadFun leave\n");   

    pthread_exit(nullptr);

    return NULL;

}


static void onClientRequestMirrorStart(DeviceClient* client) {

    printf("onClientRequestMirrorStart enter\n");

#ifdef MIRROR_BACK_ENABLE
    
    mirrorBackVideoRunning = true;
    mirrorBackAudioRunning = true;


    UsbDisplayRequestMirrorDisplayResult(ScreenMirrorStream::instance()->getContext(), client->ipAddress, USBDISPLAY_MIRROR_BACK_START_SUCCESS);
    
    if(pthread_create(&mirrorBackVideoThread, nullptr, mirrorBackVideoThreadFun, client->ipAddress)) {
        printf("failed to start mirror back thread.");
        return;
    }

    if(pthread_create(&mirrorBackAudioThread, nullptr, mirrorBackAudioThreadFun, client->ipAddress)) {
        printf("failed to start mirror back thread.");
        return;
    }
    
#endif
}

static void onClientRequestMirrorStop(DeviceClient* client) {

    printf("onClientRequestMirrorStop\n");
    
#ifdef MIRROR_BACK_ENABLE

    mirrorBackVideoRunning = false;
    mirrorBackAudioRunning = false;
    
#endif
}

static void onActivateSuccess(const char* secret) {
    printf("activate success, secret=%s\n", secret);
}


static void onActivateFailed(UsbDisplayErrorCode code, const char* reason) {
    printf("onActivateFailed, code==%d, reason=%s\n", code, reason);
}

void onNewClientRequestGetAbility(const char* ip, USBDisplayAbility* ability)
{

}

void onVideoInfoUpdated(const char* ip, VideoInfo videoInfo)
{
    printf("onVideoInfoUpdated, videoInfo==%d, mirrorVideoFormat_s=%d\n", videoInfo.format, mirrorVideoFormat_s);

    if(mirrorVideoFormat_s != videoInfo.format)
    {
        mirrorVideoFormat_s = videoInfo.format;
        
        VideoDecFormat decFormat;
        memset(&decFormat, 0, sizeof(VideoDecFormat));

        if(videoInfo.format == USBDISPLAY_VIDEO_FORMAT_H264)
        {
            decFormat.type = videoEncH264;
        }
        else if(videoInfo.format == USBDISPLAY_VIDEO_FORMAT_H265)
        {
            decFormat.type = videoEncH265;
        }

        ScreenMirrorStream::instance()->setVideoDecFormat(&decFormat);
        
    }
}

void onClientRequestUpdateAudioVolume(const char* ip, double volume)
{

}

void onClientRequestBYOMMode(const char* ip, const BYOMVideoInfo* videoInfo, const ByomAudioInfo * audioInfo)
{
    printf("onClientRequestBYOMMode success, clientip=%s, videoInfo.format=%d,videoInfo.resolution=%d, videoInfo.fps=%d, audioInfo.format=%d,audioInfo.sampleRate=%d, audioInfo.channelCount=%d\n", 
            ip, videoInfo->format, videoInfo->resolution, videoInfo->fps,
            audioInfo->format,audioInfo->sampleRate, audioInfo->channelCount);

#ifdef BYOM_ENABLE

    mirrorBackVideoRunning = true;
    mirrorBackAudioRunning = true;
    
    if(pthread_create(&mirrorBackVideoThread, nullptr, mirrorBackVideoThreadFun, ip)) {
        printf("failed to start mirror back thread.");
        return;
    }

    if(pthread_create(&mirrorBackAudioThread, nullptr, mirrorBackAudioThreadFun, ip)) {
        printf("failed to start mirror back thread.");
        return;
    }
    
#endif
}
void onClientRequestStopByom(const char* ip)
{
    printf("onClientRequestStopByom\n");
#ifdef BYOM_ENABLE
    if(currentMirrorIp == ip){
        mirrorBackVideoRunning = false;
        mirrorBackAudioRunning = false;
    }
 
#endif
}

void onClientRequestAuthorize(const char* ip)
{

}


/*--------------------------------------------------------------------------*/
//url:视频地址
//fPosition:视频占总长百分比(0-1)
//dPosition:视频其实秒数(x1000)
void airplayOpenUrl(void *cls, const char* ip, char *url, double currentPosition, double currentPositionSeconds){
    printf("air_buffer airplay_open：ip=%s, url=%s, fPosition=%f, dPosition=%f\n", ip, url, currentPosition, currentPositionSeconds);
}
//videoUrl:视频流地址
//audioUrl:音频流地址
//fPosition:视频百分比断点
//dPosition:视频秒数断点(x1000)
void airplayOpenDoubleUrl(void *cls, const char* ip, char *videoUrl,char *audioUrl, double currentPosition, double currentPositionSeconds){
    printf("air_buffer airplay_open：ip=%s, videoUrl=%s, audioUrl=%s,position=%f, dPosition=%f\n", ip, videoUrl,audioUrl, currentPosition, currentPositionSeconds);
}
void airplayPlayerPlay(void *cls, const char* ip){
    printf("airplay_play:%s\n", ip);

}
void airplay_pause(void *cls, const char* ip){
    printf("airplay_pause: %s\n", ip);
}
void airplay_stopE(void *cls, const char* ip){
    printf("airplay_stopE: %s\n", ip);
}

void airplay_remove_url(void *cls, const char* ip){
    printf("airplay_remove_url: %s\n", ip);
}

void airplay_seek(void *cls, const char* ip, long fPosition){
    printf("airplay_seek, ip=%s, fPosition=%ld\n", ip, fPosition);
}
void airplay_setvolume(void *cls, const char* ip, int volume){
    printf("airplay_setvolume, ip=%s, volume=%d\n", ip, volume);
}
void airplay_showphoto(void *cls, const char* ip, unsigned char *data, long long size){
    printf("airplay_showphoto:%s\n", ip);
}
long airplay_getduration(void *cls, const char* ip){
    printf("airplay_getduration: ip=%s\n", ip);
    return 1000;
}
long airplay_getpostion(void *cls, const char* ip){
    printf("airplay_getpostion:ip=%s\n", ip);

    return 500;
}
int airplay_isplaying(void *cls, const char* ip){
    printf("airplay_isplaying: ip=%s\n", ip);

    return 1;
}
int airplay_ispaused(void *cls, const char* ip){
    printf("airplay_ispaused:%s\n", ip);
    return 0;
}

void audio_init(void *cls, const char* ip, int bits, int channels, int samplerate, int isaudio){
    printf("audio_init: ip=%s, bits=%d, channel=%d, samplerate=%d, isAudio=%d\n", ip, bits, channels, samplerate, isaudio);

    AudioInAttr format = {0};
    format.enSampleFormat = SAMPLE_FMT_S16;               	
    format.enAiLayout = AI_NORMAL;
    format.source = EXTERNAL_IN_TYPE;
    format.u32SampleRate = samplerate;
    format.u32Channels = channels;
    format.u32NbSamples = 768;
    ScreenMirrorStream::instance()->setAudioFormat(format);
}
void audio_process(void *cls, const char* ip, const void *buffer, int buflen, uint64_t timestamp, uint32_t seqnum){
    //printf("audio_process,ip=%s, length=%d, timestamp=%lld\n", ip, buflen, timestamp);
	
	//FILE_write("./test.pcm", (char *)buffer,  buflen);

#if 1
    StreamAbility ability = ScreenMirrorStream::instance()->getPlayAbility();
    if((ability == VIDEO_AUDIO) || (ability == AUDIO_ONLY))
    {
        ScreenMirrorStream::instance()->sendAudioPacket(buffer, buflen, timestamp);
    }
#endif  

    static uint64_t printCnt = 0;

    if(printCnt++ % 640 == 0)
    {
         tracef("AirplayAudioMirrorFrame receive success, length=%d\n", buflen);
         printCnt = 1;
    }
}
void audio_destory(void *cls, const char* ip){
    printf("audio_destory:%s\n", ip);
}
void audio_setvolume(void *cls, const char* ip, float volume){
    printf("audio_setvolume, ip=%s, audio_setvolume=%f\n", ip, volume);
}
void audio_setmetadata(void *cls, const char* ip, const void *buffer, int buflen){
    printf("audio_setmetadata, ip=%s, bufLen=%d\n", ip, buflen);
}
void audio_setcoverart(void *cls, const char* ip, const void *buffer, int buflen){
    printf("audio_setcoverart, ip=%s, bufLen=%d\n", ip, buflen);
}
void audio_flush(void *cls, const char* ip){
    printf("audio_flush:%s\n", ip);
}

void AirplayCreateConnection(void *cls, const char* ip) {
    printf("AirplayCreateConnection:%s\n", ip);
    ScreenMirrorStream::instance()->setAirplayConnect(true);
#if RECORD_H264
    char logFileName[MAX_FILE_NAME_LENGTH];
    sprintf(logFileName, "./%s.h264", ip);
    int fd = open(logFileName, O_WRONLY|O_CREAT, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
    if (strcmp(ip, DEVICE_1_ADDRESS) == 0 ) {
        device1Fd = fd;
    } else if (strcmp(ip, DEVICE_2_ADDRESS) == 0) {
        device2Fd = fd;
    }
#endif

}

void AirplayTearDownConnection(void *cls, const char* ip) {
    printf("air_buffer AirplayTearDownConnection:%s\n", ip);

#if RECORD_H264
    if (strcmp(ip, DEVICE_1_ADDRESS) == 0) {
        close(device1Fd);
    } else if (strcmp(ip, DEVICE_2_ADDRESS) == 0) {
        close(device2Fd);
    }
#endif

    if(clientInfoMutex_s.try_lock())
    {
        airpalyClientInfo_s.erase(remove(airpalyClientInfo_s.begin(), airpalyClientInfo_s.end(), ip), airpalyClientInfo_s.end());

        if(usbDispalyClientInfo_s.size() == 0 && airpalyClientInfo_s.size() == 0
            && ScreenMirrorStream::instance()->getShareScreenStatus())
        {
            ScreenMirrorStream::instance()->streamLeaveDel();            
        }
        clientInfoMutex_s.unlock();
    }
}

//视频流播放
void airplayVideoMirrorFrame(void *cls, const char* ip, const unsigned char *buffer, int buflen, uint64_t timestamp){
    //printf("airplayVideoMirrorFrame, ip=%s length=%d, type=%d, timestamp=%lld\n", ip, buflen, (buffer[4] & 0x1f), timestamp);
#if RECORD_H264
    int fd = -1;
    if (strcmp(ip, DEVICE_1_ADDRESS) == 0) {
        fd = device1Fd;
    } else if (strcmp(ip, DEVICE_2_ADDRESS) == 0) {
        fd = device2Fd;
    }
    if (fd != -1) {
		//printf("write fd:%d", fd);
        write(fd, buffer, buflen);
    }

#endif
    if(currentMirrorIp != ip)
    {
        return; //滤出干扰帧
    }
    
    if(dropAirplayFrameFlg_s)
    {       
        if(buflen > 4)
        {
            int frameType = H264_TYPE(buffer[4]);
            if(0x07 == frameType) //SPS
            {
                dropAirplayFrameFlg_s = false;
                tracef("ScreenMirrorStream::airplayVideoMirrorFrame dropFrame done\n");
            }
            else
            {
                return;
            }
        }
        else
        {
            return;
        }
    }


   

    static uint64_t printCnt = 0;

#if 1

    StreamAbility ability = ScreenMirrorStream::instance()->getPlayAbility();
    if((ability == VIDEO_AUDIO) || (ability == VIDEO_ONLY))
    {
		 //ScreenMirrorStream::instance()->setVideoPacket(buffer, buflen, timestamp);

        ScreenMirrorStream::instance()->saveToCommQueue(buffer, buflen, timestamp, 0);
    }
#endif

    if(printCnt++ % 320 == 0)
    {
         LOG_PrintWarn("AirplayVideoMirrorFrame receive success\n");
         printCnt = 1;
    }
    
}

//视频开始播放设置
void airplayVideoMirrorStart(void *cls, const char* ip){
    printf("airplayVideoMirrorStart:%s\n", ip);

    dropAirplayFrameFlg_s = true;
    currentMirrorIp = ip;

    clientInfoUpdate(-1, ip);

    ScreenMirrorStream::instance()->streamComeDel(-1, ip);
    
    ScreenMirrorStream::instance()->updateServerPassword();

}

//视频停止回调
void airplayVideoMirrorStop(void *cls, const char* ip){
    printf("airplayVideoMirrorStop:%s\n", ip);

    ScreenMirrorStream::instance()->streamLeaveDel();
}


//镜像心跳检测
void mirroring_live(void *cls, const char* ip){
    //printf("mirroring_live:%s\n", ip);
}

void airplay_update_device_info(void* cls, const char* ip, const char* name,const AirplayDeviceModel model) {
    printf("airplay_update_device_info ip=%s, name=%s,model=%d\n", ip, name, model);

    //clientInfoUpdate(-1, ip);
}

void airplay_get_ability(void *cls, AirplayReceiverAbility* ability) {
    printf("airplay_get_ability\n");
    ability->maxVideoFps = 30;
    ability->resolution = AIRPLAY_RESOLUTION_1080;
    ability->orientation = AIRPLAY_ORIENTATION_LANDSCAPE;
}

void airplay_log_callback(const char* msg) {
    printf("airplay log callback:%s\n", msg);
}

void airplay_activate_success(const char* secret) {
    printf("activate success:%s\n", secret);
ScreenMirrorStream::instance()->setActiveCode(secret);

    int ret = INI_KeySet(INI_NETWORK_PATH, "network", "active_code", secret);
    if (ret)
    {
        LOG_PrintError("Fail to set active_code key.\n");
    }    
}

void airplay_activate_failed(BZAirplayErrorCode error, const char* reason) {
    printf("activate failed, error:%d, reason:%s\n", error, reason);

}

void airplay_auth_activate_success(const char* ip,const char* password){
    printf("auth callback activate success ip=%s pwd=%s\n",ip,password);
    ScreenMirrorStream::instance()->setAirplayConnect(false);
}   

void airplay_auth_activate_fail(const char* ip,const char* password){
    printf("auth callback activate fail ip=%s pwd=%s\n",ip,password);

}

void airplay_auth_activating(const char* ip,const char* password){
    printf("auth callback activating ip=%s pwd=%s\n",ip,password);

}
#endif

ScreenMirrorStream*     ScreenMirrorStream::sm_mirrorSteramIns;
std::mutex 		        ScreenMirrorStream::sm_insMutex;

ScreenMirrorStream *ScreenMirrorStream::instance()
{
	if(sm_mirrorSteramIns == NULL)
    {
        std::lock_guard<std::mutex> guard(sm_insMutex);
        if(sm_mirrorSteramIns == NULL)
        {
            sm_mirrorSteramIns = new ScreenMirrorStream();
        }
    }
    return sm_mirrorSteramIns;
}


ScreenMirrorStream::ScreenMirrorStream() 
: m_hasInited(false)
, m_curStreamType(PRIVATE)
, m_activeCode("")//k18f36 //g12357 /vd41b9 /pc791c-880KJ8-GQMfXaWFx97j6hKI /b90803
, m_activateSecret("") //需要联网访问usbdisplay.cn获取 //g12357->tFo0lLd6Oz7gHdafGL-l97c m6ce0d->7TZYjE4PTx-BNhMzgbaWe-c u2e2a4->azob7lW_CtRUWjG4iTDiYWw
, m_videoChannel(-1)
, m_started(false)
, m_audioChannel(-1)
, m_playAbility(VIDEO_AUDIO)
{

    //m_videoChannel = VideoDecode::getVideoDecChannel();
    //m_pVideoDecode = VideoDecode::instance(m_videoChannel);    
   
    
    //m_videoPacket.buffer = (uchar *)malloc(MIRROR_WIDTH * MIRROR_HEIGHT * 3/2);

    //m_audioPacket.buffer = (uchar *)malloc(4096);

}

bool ScreenMirrorStream::getDeviceMac(void)
{   
    char ethernet[16] = "eth0";
    int ret = NetGetMAC(ethernet,
                 m_macAddrStr,
                 sizeof(m_macAddrStr));
    if (ret)
    {
        LOG_PrintError("Fail to get mac.\n");
        return false;
    }

    LOG_PrintInfo("macaddrStr:%s\n", m_macAddrStr);
    return true;
}

void ScreenMirrorStream::initUsbDisplayCallback(void) 
{
    m_usbDisplayParameter.cbs.onClientConnected = onClientConnected;
    
    m_usbDisplayParameter.cbs.onClientDisconnected = onClientDisconnected;
    m_usbDisplayParameter.cbs.onDeviceNameUpdated = onClientNameUpdated;
    m_usbDisplayParameter.cbs.onDeviceTypeUpdated = onClientTypeUpdated;
    m_usbDisplayParameter.cbs.onDeviceResolutionChanged = onClientResolutionChanged;
    m_usbDisplayParameter.cbs.onDeviceShow = onClientShow;
    m_usbDisplayParameter.cbs.onDeviceHide = onClientHide;
    m_usbDisplayParameter.cbs.onVideoFrame = onVideoFrame;
    m_usbDisplayParameter.cbs.onAudioFrame = onAudioFrame;
    m_usbDisplayParameter.cbs.isPermitToShow = isPermitToShow;
    m_usbDisplayParameter.cbs.onAudioInfoUpdated = onAudioInfoUpdated;
    m_usbDisplayParameter.cbs.onVideoInfoUpdated = onVideoInfoUpdated;

    m_usbDisplayParameter.cbs.onUsbDeviceAttached = onUsbDeviceAttached123;
    m_usbDisplayParameter.cbs.onUsbDeviceDetached= onUsbDeviceDetached;
    m_usbDisplayParameter.cbs.onUsbDeviceReady = onUsbDeviceReady;
    m_usbDisplayParameter.cbs.onUsbDeviceRequestVersionInfoSuccess = onUsbDeviceGetVersionSuccess;
    m_usbDisplayParameter.cbs.onConfigUsbDeviceSuccess = onUsbDeviceConfigureSuccess;
    m_usbDisplayParameter.cbs.onUpgradeUsbDeviceStarted = onUsbDeviceUpgradeStarted;
    m_usbDisplayParameter.cbs.onUpgradeUsbDeviceInProgress = onUsbDeviceUpgradeInProgress;
    m_usbDisplayParameter.cbs.onUpgradeUsbDeviceSuccess = onUsbDeviceUpgradeSuccess;
    m_usbDisplayParameter.cbs.onUpgradeUsbDeviceFailed = onUsbDeviceUpgradeFailed;
    m_usbDisplayParameter.cbs.UsbDisplayLog = onUsbDisplayLog;

    m_usbDisplayParameter.cbs.onClientRequestMirrorBackStart = onClientRequestMirrorStart;
    m_usbDisplayParameter.cbs.onClientRequestMirrorBackStop = onClientRequestMirrorStop;
    m_usbDisplayParameter.cbs.onActivateSuccess = onActivateSuccess;
    m_usbDisplayParameter.cbs.onActivateFailed = onActivateFailed;

    m_usbDisplayParameter.cbs.onNewClientRequestGetAbility = onNewClientRequestGetAbility;
    m_usbDisplayParameter.cbs.onVideoInfoUpdated = onVideoInfoUpdated;
    m_usbDisplayParameter.cbs.onClientRequestUpdateAudioVolume = onClientRequestUpdateAudioVolume;
    m_usbDisplayParameter.cbs.onClientRequestBYOMMode = onClientRequestBYOMMode;
    m_usbDisplayParameter.cbs.onClientRequestStopByom = onClientRequestStopByom;
    m_usbDisplayParameter.cbs.onClientRequestAuthorize = onClientRequestAuthorize;

    m_usbDisplayParameter.cbs.onDeviceUpdateTransmitterId = onDeviceUpdateTransmitterId;
}


bool ScreenMirrorStream::usbDisplayInit(void) 
{

    m_usbDisplayParameter = createDefaultParameter();
    strcpy(m_usbDisplayParameter.serverName, m_deviceServerName.c_str());
    strcpy(m_usbDisplayParameter.serverVersion, "2.3.0");
    m_usbDisplayParameter.interface = USB_INTERFACE_ETHERNET; //interface //netInterface
    m_usbDisplayParameter.racing = true;
    m_usbDisplayParameter.maxMirroringCount = 1;
    m_usbDisplayParameter.logLevel = USBDISPLAY_LOG_INFO;
    m_usbDisplayParameter.discoverable = USBDISPLAY_TRUE;
    
    m_usbDisplayParameter.functions = createDefaultSupportFunctions();
    m_usbDisplayParameter.functions.audioTypePcm = true;
    m_usbDisplayParameter.functions.audioTypeAac = false;

#ifdef MIRROR_BACK_ENABLE    
    m_usbDisplayParameter.functions.mirrorBack = true;
#else    
    m_usbDisplayParameter.functions.supportByomMode = true;
#endif

    int size = sizeof(m_usbDisplayParameter.mac);
    strncpy(m_usbDisplayParameter.mac, m_macAddrStr, size); //填入机器的Mac地址，需要跟 @interface 匹配
    m_usbDisplayParameter.mac[size-1] = '\0';

    size = sizeof(m_usbDisplayParameter.devicePassword);
    strncpy(m_usbDisplayParameter.devicePassword, getdevicePassword().c_str(), size);//连接密码
    m_usbDisplayParameter.devicePassword[size-1] = '\0';
    
    size = sizeof(m_usbDisplayParameter.code);
    strncpy(m_usbDisplayParameter.code, m_activeCode.c_str(), size); // 需要跟供应商那边拿激活码x5cf8d // i743a2
    m_usbDisplayParameter.code[size-1] = '\0';

    /*size = sizeof(m_usbDisplayParameter.secret);
    strncpy(m_usbDisplayParameter.secret, m_activateSecret.c_str(), size);//密文信息，首次激活需要填一个空字符。当激活成功后，会回调激活密文回来，后续的启动就传入这个密文。
    m_usbDisplayParameter.secret[size-1] = '\0';*/

    initUsbDisplayCallback();

    int iRet = UsbDisplayInit(&m_usbDisplayContext, m_usbDisplayParameter);
    if(iRet != USBDISPLAY_ERROR_OK)
    {
        errorf("UsbDisplayInit failed,iRet=%d, ok=%d\n", iRet, USBDISPLAY_ERROR_OK);
        return false;
    }  

    tracef("UsbDisplayInit success--------------,SDK_VERSION:%s\n",SDK_VERSION);
    return true;
}

bool ScreenMirrorStream::airplayInit(void) 
{
    ///初始化配置参数
    m_airplayParameter = GetDefaultParameters();

    int size = sizeof(m_airplayParameter.name);
    strncpy(m_airplayParameter.name, m_deviceServerName.c_str(), size);
    m_airplayParameter.name[size-1] = '\0';

    
    strcpy(m_airplayParameter.password, getdevicePassword().c_str());
    m_airplayParameter.airplayResolution = AIRPLAY_RESOLUTION_1080;
    strcpy(m_airplayParameter.fileDir,"/tmp");
    m_airplayParameter.activateInterface = AIRPLAY_INTERFACE_ETHERNET;
    m_airplayParameter.airplayOrientation = AIRPLAY_ORIENTATION_LANDSCAPE;
    m_airplayParameter.discoverable = true;
    m_airplayParameter.targetFps = 30;
    m_airplayParameter.supportUrl = 0;
    strcpy(m_airplayParameter.customerCode, "HAMEDAL_TEM_MEETING");//customerCode用于授权

    size = sizeof(m_airplayParameter.macAddress);
    strncpy(m_airplayParameter.macAddress, m_macAddrStr, size); //填入机器的Mac地址，需要跟 @interface 匹配
    m_airplayParameter.macAddress[size-1] = '\0';

    size = sizeof(m_airplayParameter.activateCode);
    strncpy(m_airplayParameter.activateCode, m_activeCode.c_str(), size); // 需要跟供应商那边拿激活码x5cf8d // i743a2
    m_airplayParameter.activateCode[size-1] = '\0';

    
    char activeCode[64] = {0};
    int ret = INI_KeyGetString(INI_NETWORK_PATH, "network", "active_code", activeCode);
    if (ret)
    {
        LOG_PrintError("Fail to get active_code key.\n");
    }
    m_activateSecret = activeCode;
	

    size = sizeof(m_airplayParameter.activateSecret);
    strncpy(m_airplayParameter.activateSecret, m_activateSecret.c_str(), size);//密文信息，首次激活需要空字符串。当激活成功后，会回调激活密文回来，后续的启动就传入这个密文。
    m_airplayParameter.activateSecret[size-1] = '\0';

    ///定义Airplay的各种回调接口
    memset(&m_airplayCallFun, 0, sizeof(airplay_callbacks_t));
    m_airplayCallFun = GetDefaultFunctions();

    m_airplayCallFun.airplay_connection_create    = AirplayCreateConnection;
    m_airplayCallFun.airplay_connection_teardown  = AirplayTearDownConnection;

    m_airplayCallFun.AirPlayPlayback_Open			= airplayOpenUrl;
    m_airplayCallFun.AirPlayPlaybackDouble_Open   = airplayOpenDoubleUrl;
    m_airplayCallFun.AirPlayPlayback_Play			= airplayPlayerPlay;
    m_airplayCallFun.AirPlayPlayback_Pause		= airplay_pause;
    m_airplayCallFun.AirPlayPlayback_Stop			= airplay_stopE;
    m_airplayCallFun.AirplayPlayback_remove       = airplay_remove_url;
    m_airplayCallFun.AirPlayPlayback_Seek			= airplay_seek;
    m_airplayCallFun.AirPlayPlayback_SetVolume	= airplay_setvolume;
    m_airplayCallFun.AirPlayPlayback_ShowPhoto	= airplay_showphoto;
    m_airplayCallFun.AirPlayPlayback_GetDuration	= airplay_getduration;
    m_airplayCallFun.AirPlayPlayback_GetPosition  = airplay_getpostion;
    m_airplayCallFun.AirPlayPlayback_IsPlaying	= airplay_isplaying;
    m_airplayCallFun.AirPlayPlayback_IsPaused		= airplay_ispaused;
    //...
    m_airplayCallFun.AirPlayAudio_Init			= audio_init;
    m_airplayCallFun.AirPlayAudio_Process			= audio_process;
    m_airplayCallFun.AirPlayAudio_destroy			= audio_destory;
    m_airplayCallFun.AirPlayAudio_SetVolume		= audio_setvolume;
    m_airplayCallFun.AirPlayAudio_SetMetadata		= audio_setmetadata;
    m_airplayCallFun.AirPlayAudio_SetCovertArt	= audio_setcoverart;
    m_airplayCallFun.AirPlayAudio_Flush			= audio_flush;
    //...
    m_airplayCallFun.AirPlayMirroring_start		= airplayVideoMirrorStart;
    m_airplayCallFun.AirPlayMirroring_Process		= airplayVideoMirrorFrame;
    m_airplayCallFun.AirPlayMirroring_Stop		= airplayVideoMirrorStop;
    m_airplayCallFun.AirPlayMirroring_Live		= mirroring_live;

    m_airplayCallFun.AirplayUpdateDeviceInformation            = airplay_update_device_info;
    m_airplayCallFun.AirplayGetAbility            = airplay_get_ability;
    m_airplayCallFun.airplay_log_callback         = airplay_log_callback;
    m_airplayCallFun.airplay_activate_success     = airplay_activate_success;
    m_airplayCallFun.airplay_activate_failed      = airplay_activate_failed;

    m_airplayCallFun.AirplayAuthActivateSuccess     = airplay_auth_activate_success;
    m_airplayCallFun.AirplayAuthActivateFail        = airplay_auth_activate_fail;
    m_airplayCallFun.AirplayAuthActivating          = airplay_auth_activating;

    return true;
}

bool ScreenMirrorStream::airplayStart(void) 
{
    int iRet = BZAirplayReceiverStartServer(&m_airplayParameter, &m_airplayCallFun);
    if(iRet)
    {
        errorf("BZAirplayReceiverStartServer failed，iRet=%d,m_activateSecret=%s\n",iRet,m_activateSecret.c_str());
        return false;
    }

    BZAirplayReceiverSetAuthState(1, m_devicePassword.c_str());

    tracef("BZAirplayReceiverStartServer success\n");

    return true;
}

bool ScreenMirrorStream::airplayStop(void) 
{
    BZAirplayReceiverStopServer();

    tracef("BZAirplayReceiverStopServer success\n");

    return true;
}

bool ScreenMirrorStream::usbDisplayStart(void) 
{
    int iRet = UsbDisplayStart(m_usbDisplayContext);
    if(iRet != USBDISPLAY_ERROR_OK)
    {
        errorf("UsbDisplayStart failed,iRet=%d\n", iRet);
        return false;
    }

    tracef("usbDisplayStart success\n");

    return true;
}

bool ScreenMirrorStream::usbDisplayStop(void) 
{
    int iRet = UsbDisplayStop(m_usbDisplayContext);
    if(iRet != USBDISPLAY_ERROR_OK)
    {
        errorf("UsbDisplayStart failed\n");
        return false;
    }

    return true;
}

bool ScreenMirrorStream::usbDisplaySetFormat(const Json::Value &table) 
{
    //UsbDisplayRequestUpdateGlobalTargetFrameRate; //帧率、分辨率、码率控制

    return true;
}

UsbDisplayContext* ScreenMirrorStream::getContext()
{
    return m_usbDisplayContext;
}

bool ScreenMirrorStream::streamInit()
{
    if(!m_hasInited)
    {
        getDeviceMac();
        //开启服务前确定服务的名称
        Json::Value nameTable;
        IConfigInterface::GetInstance()->Get("DevName", nameTable);
        if(nameTable.isMember("Name") && nameTable["Name"].isString()){
            m_deviceServerName = nameTable["Name"].asString();
        }else{
            m_deviceServerName = "";
        }
        //开启服务前确定服务的随机密码4位
        int random = generateRandomFourDigitNumber();
        setdevicePassword(std::to_string(random));
        LOG_PrintWarn("------------------------------m_deviceServerName:%s            m_devicePassword:%s\n", m_deviceServerName.c_str(), getdevicePassword().c_str());
        if(!usbDisplayInit() || !airplayInit())
        {
            errorf("streamInit failed\n");
            return false;
        }
        m_hasInited = true;

        //setStreamDisplayChn(0);

        m_streamInThread.start([this](Fdt::Thread *thread){this->StreamInProc(thread);}); //启动单独线程处理视频流

        //m_streamAudioThread.start([this](Fdt::Thread *thread){this->StreamInAudioProc(thread);}); //启动单独线程处理音频流
    }
    return true;
}


std::string ScreenMirrorStream::getdevicePassword(){
    std::lock_guard<std::mutex> lock(m_pwdLock);
    return m_devicePassword;
}

bool ScreenMirrorStream::setdevicePassword(std::string pwd){
    std::lock_guard<std::mutex> lock(m_pwdLock);
    m_devicePassword = pwd;
    return true;
}

//std::string getdeviceServerName();

//bool setdeviceServerName(std::string serverName);

bool ScreenMirrorStream::setAirplayConnect(bool status){
    std::lock_guard<std::mutex> lock(m_airplayConnectLock);
    m_airplayConnect = status;
    return true;
}

bool ScreenMirrorStream::getAirplayConnect(){
    std::lock_guard<std::mutex> lock(m_airplayConnectLock);
    return m_airplayConnect;
}

bool ScreenMirrorStream::setUsbDisplayConnect(bool status){
    std::lock_guard<std::mutex> lock(m_usbConnectLock);
    m_usbdisplayConnect = status;
    return true;    
}

bool ScreenMirrorStream::isActived(){
    std::lock_guard<std::mutex> lock(m_airplayConnectLock);
    return !m_activateSecret.empty();
}

void ScreenMirrorStream::setActiveCode(const char *code){
    std::lock_guard<std::mutex> lock(m_airplayConnectLock);
    m_activateSecret = code;
}

bool ScreenMirrorStream::getUsbDisplayConnect(){
    std::lock_guard<std::mutex> lock(m_usbConnectLock);
    return m_usbdisplayConnect;
}



int ScreenMirrorStream::generateRandomFourDigitNumber() {
    // 使用随机数引擎和分布器
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> distribution(1000, 9999);

    // 生成四位随机数
    int randomFourDigitNumber = distribution(gen);

    LOG_PrintWarn("randomFourDigitNumber-----------------------------------%d\n", randomFourDigitNumber);

    return randomFourDigitNumber;
}

bool ScreenMirrorStream::updateServerPassword() {
    std::lock_guard<std::mutex> lock(m_UserPwdLock);
    int random = generateRandomFourDigitNumber();
    std::string devicePwd = std::to_string(random);
    
    UsbDisplayUpdate(m_usbDisplayContext, m_deviceServerName.c_str(), devicePwd.c_str(), USBDISPLAY_TRUE, USBDISPLAY_FALSE);
    BZAirplayReceiverSetAuthState(1, devicePwd.c_str());
    setdevicePassword(devicePwd);
    return true;
}

bool ScreenMirrorStream::streamStart()
{
    switch(m_curStreamType)
    {
        case PRIVATE:
        {
            usbDisplayStart();

            airplayStart(); //airpaly同时启动
            break;
        }
        case AIRPLAY:
        {
            airplayStart();                
            break;
        }
        default :
            return false;
    }

    /*if(m_taskInfo.StopTime != -1)
    {
        m_taskTimer.reset(new Fdt::Timer(m_taskInfo.StopTime * 1000, ([this](){return this->stop();}), nullptr)); //不是循环播放，注册停止函数
    }
    else*/
    {
        m_taskTimer.reset();
    }

    return true;
}

bool ScreenMirrorStream::mirrorAVStart()
{
    if(!m_pVideoDecode)
    {
        return false;
    }

    return m_pVideoDecode->start();
}

bool ScreenMirrorStream::mirrorAVStop()
{
    LOG_PrintWarn("mirrorAVStop enter\n");
    if(!m_pVideoDecode)
    {
        return false;
    }

    return m_pVideoDecode->stop();
}



void ScreenMirrorStream::setAudioFormat(AudioInAttr format){
    if(m_pAudioInput) m_pAudioInput->setFormat(format);
}

bool ScreenMirrorStream::start(StreamPlayInfo playInfo)
{
    LOG_PrintWarn("type=%d, streamInfo=%s, playAbility=%d, audioChn=%d, videoChn=%d\n",
                playInfo.stream.type,playInfo.stream.content, playInfo.playAbility, playInfo.audioChn, playInfo.videoChn);

    streamInit();
  
    if(!m_started)
    {
        std::string streamInfo = playInfo.stream.content;
        m_playAbility = playInfo.playAbility;
        
        if(!setStreamType(streamInfo))
        {
            return false;
        }

        ///创建视频解码并启动
        if((m_playAbility == VIDEO_AUDIO) || (m_playAbility == VIDEO_ONLY))
        {
            if(m_videoChannel != playInfo.videoChn)
            {            
                m_videoChannel = playInfo.videoChn;
                m_pVideoDecode = VideoDecode::instance(m_videoChannel); 
            }
            if(!m_pVideoDecode)
            {
                return false;
            }

            VideoDecFormat decFormat;
            memset(&decFormat, 0, sizeof(VideoDecFormat));
            decFormat.type = videoEncH264;
            if(!m_pVideoDecode->setFormat(&decFormat))
            {
                return false;
            }
            
            /*if(!m_pVideoDecode->start()) 
            {
                return false;
            }*/
        }

        ///创建音频输入管理对象
        if((m_playAbility == VIDEO_AUDIO) || (m_playAbility == AUDIO_ONLY))
        {
            if(m_audioChannel != playInfo.audioChn)
            {            
                m_audioChannel = playInfo.audioChn;
                m_pAudioInput = AudioInMgr::instance(m_audioChannel); 

                if(!m_pAudioInput)
                {
                    return false;
                }

                AudioInDesc inDesc = {0};
                inDesc.card = 0;
                inDesc.channel = m_audioChannel;
                if(!m_pAudioInput->createAudioIn(inDesc))
                {
                    return false;
                }

                AudioInAttr format = {0};
        	    format.enSampleFormat = SAMPLE_FMT_S16;               	
            	format.enAiLayout = AI_NORMAL;
            	format.source = EXTERNAL_IN_TYPE;
            	format.u32SampleRate = 44100;
            	format.u32Channels = 2;
            	format.u32NbSamples = 768;
            	m_pAudioInput->setFormat(format);
            	
            }           
        }
 
        m_taskInfo = playInfo.task;
        m_taskTimer.reset(new Fdt::Timer(m_taskInfo.StartTime * 1000, ([this](){return this->streamStart();}), nullptr));

        m_started = true;
    }

    LOG_PrintWarn("start leave \n"); 
    return true;
}

bool ScreenMirrorStream::streamStop()
{
    switch(m_curStreamType)
    {
        case PRIVATE:
        {
            usbDisplayStop();

            airplayStop();
            break;
        }
        case AIRPLAY:
        {
            airplayStop();
            break;
        }
        default :
            return false;
    }       

    return true;
}

bool ScreenMirrorStream::stop()
{
    LOG_PrintWarn("stop enter \n");

    if(m_started)
    { 
        m_started = false;
        
        m_taskTimer.reset();

        if(!streamStop()) //停止流--后续若只是更换解码通道，无需停止。
        {
            return false;
        } 

        if((m_playAbility == VIDEO_AUDIO) || (m_playAbility == VIDEO_ONLY))
        {
            if((m_pVideoDecode == nullptr) || (!m_pVideoDecode->stop())) //停止解码--后续若只是更换流的种类，无需停止编码
            {
                return false;
            }
        }
    }

    LOG_PrintWarn("stop leave \n");
        
    return true;
}

bool ScreenMirrorStream::setStreamType(std::string type)
{
    if(type == "private")
    {
        m_curStreamType = PRIVATE;
    }
    else if(type == "airplay")
    {
        m_curStreamType = AIRPLAY;
    }
    else if(type == "miracast")
    {
        m_curStreamType = MIRACAST;
    }
    else
    {
        errorf("Mirror stream type not support\n");
        return false;
    }

    
return true;
}

void ScreenMirrorStream::setActivateSecret(std::string secret)
{
    //m_activateSecret = secret;
    printf("ScreenMirrorStream secret=%s\n", secret.c_str());
    
	Json::Value table;
	table["ActivateSecret"] = secret; 
    IConfigInterface::GetInstance()->Set("Mirror", table, ConfigOptions::ConfigOptionPart);
}

bool ScreenMirrorStream::setFormat(const Json::Value &table)
{
    std::lock_guard<std::mutex> guard(m_paramMutex);
	return true;
}

bool ScreenMirrorStream::setVideoPacket(const unsigned char *buffer, int buflen, uint64_t timestamp)
{
    if( m_pVideoDecode)
    {
        m_videoPacket.buffer = buffer;
        
        m_videoPacket.length = buflen;
        m_videoPacket.pts = timestamp;

        return m_pVideoDecode->putPacket(&m_videoPacket);
    }
    
    return false;
}

bool ScreenMirrorStream::sendAudioPacket(const unsigned char *buffer, int buflen, uint64_t timestamp)
{
    if(m_pAudioInput)
    {
        m_audioPacket.buffer = buffer;
        m_audioPacket.length = buflen;
        m_audioPacket.pts = timestamp;
        
        return m_pAudioInput->putPacket(&m_audioPacket);
    }

    return false;
}

StreamAbility ScreenMirrorStream:: getPlayAbility()
{   
    return m_playAbility;
}

bool ScreenMirrorStream::MirrorCodeRefresh()
{
    std::lock_guard<std::mutex> guard(m_codeMutex);
    m_codeTimerStatus = false;

    tracef("MirrorCodeRefresh enter\n");   
    return false;
}

bool ScreenMirrorStream::getMirrorCode(std::string& pinCode)
{
    std::lock_guard<std::mutex> guard(m_codeMutex);
    
    if(m_pinCode.size() == 0 || !m_codeTimerStatus)
    {
        char *pInterfaceName = "eth0";
        char devIp[64] = {0};
        char netmaskStr[16] = {0};
        int ret = NetGetHostIPEx(pInterfaceName, devIp,sizeof(devIp),
                 			netmaskStr, sizeof(netmaskStr));
        
        int prefix = rand() % 100; 
        unsigned char value[4] = { 0 };
        size_t index = 0;
        char* ipAddr = devIp;

        while (*ipAddr) 
        {
            if (isdigit((unsigned char)*ipAddr)) 
            {
                value[index] *= 10;
                value[index] += *ipAddr - '0';
            }
            else 
            {
                index++;
            }
            
            ipAddr++;
        }

        int numA = value[2];        
        int numB = value[3];          
        int va = numA ^ prefix;        
        int vb = numB ^ prefix;   

        char tmpstr[255];
        sprintf(tmpstr, "%d",va);
        string sa = tmpstr;      
        while (sa.length() < 3) 
        {            
            sa = "0" + sa;        
        }   

        sprintf(tmpstr, "%d",vb);
        string sb = tmpstr;     
        while (sb.length() < 3) 
        {            
            sb = "0" + sb;        
        }   

        sprintf(tmpstr, "%d",prefix);
        string sf = tmpstr;   
        while (sf.length() < 2) 
        {            
            sf = "0" + sf;        
        } 

        pinCode = sf + sa + sb;

        m_pinCode = pinCode;
 
        m_codeTimerStatus = true;
        m_codeTimer.reset(new Fdt::Timer(10  * 60 * 1000, ([this](){return this->MirrorCodeRefresh();}), nullptr)); //不是循环播放，注册停止函数
    }
    else
    {
        pinCode = m_pinCode;
    }
    
    //tracef("getMirrorCode::pinCode result = %s\n",  m_pinCode.c_str());    
    return true;    
    
}


bool ScreenMirrorStream::outputStart()
{
    m_pVideoEncode = VideoEncode::instance(BYOM_OUT);
    m_pAudioEncode = AudioEncode::instance(BYOM_OUT);

    if(!m_pVideoEncode || !m_pAudioEncode)
    {
        errorf("m_pVideoEncode or m_pAudioEncode is NULL\n");
        return false;
    }

    bool result = false;
   
    ///VIDEO
    {
        //setFormat        
        VideoEncFormat encFormat;
        memset(&encFormat, 0, sizeof(VideoEncFormat));
        encFormat.type = videoEncH264;
        encFormat.width = MIRROR_WIDTH;
        encFormat.height = MIRROR_HEIGHT;
        encFormat.bitrateControl = videoEncBitrateCtrlConstant;  
        encFormat.fps = 30;
        encFormat.gop = encFormat.fps*2;
        encFormat.bitrate = (1*encFormat.width*encFormat.height/1024)*encFormat.fps/5; //(1*encFormat.width*encFormat.height/1024)*2;
        encFormat.quality = 1;
        encFormat.qualityType = 0;
        encFormat.pack = videoEncPackTypeRAW;
        encFormat.profile = h264ProfileBaseline;//h264ProfileHigh;

        result = m_pVideoEncode->setFormat(&encFormat);
        if(!result)
        {
    		errorf("Video setFormat failed");
    		return false;
    	}
        //start
        result = m_pVideoEncode->start();
        if(!result)
        {
    		errorf("Video start failed");
    		return false;
    	}
	}

    ///AUDIO
    {
    	AudioEncFormat aencFormat;
        memset(&aencFormat, 0, sizeof(aencFormat));
    	aencFormat.type = audioEncPCM;
        aencFormat.pack = audioEncPackTypeRAW;
        aencFormat.frequency = 48000;
        aencFormat.channelNum = 1;
        aencFormat.depth = 16;

        result = m_pAudioEncode->setFormat(&aencFormat);
        if(!result)
        {
    		errorf("Audio setFormat failed");
    		return false;
    	}  

    	result = m_pAudioEncode->start();
        if(!result)
        {
    		errorf("Audio start failed");
    		return false;
    	} 
	}

	tracef("outputStart success");

	return true;
}

bool ScreenMirrorStream::outputStop()
{
    if(!m_pVideoEncode || !m_pAudioEncode)
    {
        errorf("m_pVideoEncode or m_pAudioEncode is NULL\n");
        return false;
    }

    bool result = false;
    
    result = m_pVideoEncode->stop();
    if(!result)
    {
		errorf("Video stop failed");
		return false;
	}
    
    result = m_pAudioEncode->stop();
    if(!result)
    {
		errorf("Audio stop failed");
		return false;
	}

	tracef("outputStop success");

	return true;
}

bool ScreenMirrorStream::VideoGetPacket(SCREEN_vencPacket_t *pPacket)
{    
    bool isH26x = false;
    std::string usbPort;

    CurtainActManager::instance()->usbVideoRealTimeInfo(usbPort, isH26x);
    if(isH26x)
    {
        return Media::UsbInStream::instance(usbPort)->directGetVideoData(pPacket);
    }
    
    if (m_pVideoEncode)
    {
        return m_pVideoEncode->getPacket(pPacket);
    }

    return true;
}
bool ScreenMirrorStream::VideoReleasePacket()
{
    bool isH26x = false;
    std::string usbPort;

    CurtainActManager::instance()->usbVideoRealTimeInfo(usbPort, isH26x);
    if(isH26x)
    {
        return true;
    }

    if(m_pVideoEncode)
    {  
        return m_pVideoEncode->releasePacket();  
    }   
    
    return false;
}


bool ScreenMirrorStream::AudioGetPacket(char *buf, int *length, uint64_t& pts)
{
    if(m_pAudioEncode)
    {    
        return m_pAudioEncode->getPacket(buf, length, pts);
    }
    
    return false;
}

bool ScreenMirrorStream::startSwitchTimer(bool state)
{
    std::lock_guard<std::mutex> guard(m_switchMutex);
    m_switchTimer.reset(new Fdt::Timer(0*1000, ([=,this](){return this->dymicSwitchCurtain(state);}), nullptr));
    return true;

}

bool ScreenMirrorStream::dymicSwitchCurtain(bool state)
{
    std::lock_guard<std::mutex> guard(m_switchMutex);

#if 1
    CurtainActManager::instance()->dymicSwitchCurtain(state);
#endif

    //m_switchTimer.reset();

    return true;
}

bool ScreenMirrorStream::saveToCommQueue(const unsigned char *buffer, int buflen, uint64_t timestamp, uint8_t index)
{
    FramePtr videoFrame(new FrameBuffer(buflen));
    videoFrame->timestamp = timestamp;
    videoFrame->size = buflen;
    memcpy(videoFrame->data, buffer, buflen);

    if (videoFrame.get() == NULL || index >= QueueArray)
    {
        return false;
    }
    
	if(m_frameaQueue[index].size() >= QueueSize)
	{
	    LOG_PrintInfo("saveToCommQueue::enter [%s] [%d] qindex=%d,size=%d\n",__FILE__,__LINE__, index, m_frameaQueue[index].size());
	    
	    m_queueMutex[index].lock();
	    m_frameaQueue[index].front();//处理队列中消息,移除最早的数据	
    	m_frameaQueue[index].pop();
    	m_queueMutex[index].unlock();

	}

    //存队列
	m_queueMutex[index].lock();
    m_frameaQueue[index].push(videoFrame);
	m_queueMutex[index].unlock();
            
	return true;
}

bool ScreenMirrorStream::getCommQueueMsg(FramePtr& msg, uint8_t index)
{
    if (index >= QueueArray)
    {
        return false;
    }

	m_queueMutex[index].lock();
	if(!m_frameaQueue[index].empty())
	{	    
    	msg = m_frameaQueue[index].front();//处理队列中消息		
    	m_frameaQueue[index].pop();
	
    	//printf("enter [%s] [%d] \n",__FILE__,__LINE__);
    	m_queueMutex[index].unlock();
    	return true;
	}
	m_queueMutex[index].unlock();
	return false;
}

bool ScreenMirrorStream::clearCommQueue()
{
    //判定视频设备的接口
    bool isH26x = false;
    std::string usbPort;

    if(CurtainActManager::instance()->usbVideoRealTimeInfo(usbPort, isH26x))
    {
        Media::UsbInStream::instance(usbPort)->clearVideoQueue(1);
    }

    for(int index = 0; index < QueueArray; ++index)
    {
    	m_queueMutex[index].lock();
        while(!m_frameaQueue[index].empty()) m_frameaQueue[index].pop();
        m_queueMutex[index].unlock();
    }

    return true;
}


void ScreenMirrorStream::StreamInProc(Fdt::Thread *thread)
{
    thread->setPriority(Fdt::PRIORITY_NORMAL, Fdt::POLICY_RR); 

    //printf("enter [%s] [%d] \n",__FILE__,__LINE__);

#if 1
    FramePtr framePtr;

    uint64_t time1 = vdo_get_time();

    const uint8_t sendFrq = 30;

    const uint16_t maxFreq = 1000;

    while(thread->running())
    {  
        if(!getShareScreenStatus())
        {
            thread->sleep(20);
            continue;
        }
        
        if(!getCommQueueMsg(framePtr, 0))
        {
            thread->sleep(3);
            continue;
        }

        //media_FILE_Write("/extern/rtsp.h264", framePtr->data, framePtr->size);

        
        setVideoPacket(framePtr->data, framePtr->size, framePtr->timestamp);

        uint64_t runtime = vdo_get_time() - time1;
        if(runtime < sendFrq)
        {   
            thread->sleep(sendFrq - runtime); 
            
            //LOG_PrintWarn("StreamInProc  runtime=%llu\n", runtime);
        }
        else if(runtime > maxFreq) //下一次连接
        {
            thread->sleep(sendFrq);

            LOG_PrintWarn("ScreenMirrorStream ::StreamInProc  over maxFreq runtime=%llu, maxFreq=%u\n", runtime, maxFreq);
        }

        time1 = vdo_get_time();

    }
#endif
    
}

void ScreenMirrorStream::StreamInAudioProc(Fdt::Thread *thread)
{
    thread->setPriority(Fdt::PRIORITY_NORMAL, Fdt::POLICY_RR); 

    //printf("enter [%s] [%d] \n",__FILE__,__LINE__);

#if 1
    FramePtr framePtr;

    unsigned char muteData[1024] = {0};
    int muteLen = 512;  

    /*uint64_t refTime = 0;
    uint64_t curTime = 0;
    uint64_t runTime = 0;*/

    uint64_t time1 = vdo_get_time();

    const uint8_t sendFrq = 14;

    const uint16_t maxFreq = 500;
    
    while(thread->running())
    {        
        if(!getCommQueueMsg(framePtr, 1))
        {
            thread->sleep(1);
            continue;
        }

        /*curTime = vdo_get_time();
        runTime = curTime - refTime;
        if(runTime > 100)
        {
            LOG_PrintWarn("StreamInAudioProc::getCommQueueMsg audio  runtime=%llu\n", runTime);

            //sendAudioPacket(muteData, muteLen, curTime);

            refTime = vdo_get_time();
        }*/

        
        sendAudioPacket(framePtr->data, framePtr->size, framePtr->timestamp);

        uint64_t runtime = vdo_get_time() - time1;
        if(runtime < sendFrq)
        {   
            thread->sleep(sendFrq - runtime); 
            
            //LOG_PrintWarn("StreamInProc  runtime=%llu\n", runtime);
        }
        else if(runtime > maxFreq) //下一次连接
        {
            thread->sleep(sendFrq);

            LOG_PrintWarn("ScreenMirrorStream ::StreamInAudioProc  over maxFreq runtime=%llu, maxFreq=%u\n", runtime, maxFreq);
        }

        time1 = vdo_get_time();
    }
#endif
    
}

bool ScreenMirrorStream::setVideoDecFormat(VideoDecFormat *format)
{   
    if((m_pVideoDecode == nullptr) || (!m_pVideoDecode->stop()))
    {
        return false;
    }
    
    if(!m_pVideoDecode->setFormat(format))
    {
        return false;
    }

    if(!m_pVideoDecode->start()) 
    {
        return false;
    }

    return true;
}

bool ScreenMirrorStream::HdmioutControl(uint8_t cmd)
{
    Json::Value hdmiInfo;
    IConfigInterface::GetInstance()->Get("Hdmi", hdmiInfo);
	bool value = hdmiInfo["HdmioutControl"].asBool();

	if(!value)
	{
        return false;
	}
		
    VIDEO_HdmioutControl(cmd); //HDMIOUT使能控制  

    return true;
}

bool ScreenMirrorStream::setShareScreenStatus(bool state)
{
    m_shareScreenState = state;
    return true;
}

bool ScreenMirrorStream::getShareScreenStatus()
{   
    return m_shareScreenState;
}

bool ScreenMirrorStream::streamComeDel(int clientType, const char *ip)
{
    clearCommQueue();

    setShareScreenStatus(true);
    
    WlanService::instance()->setMirrorIp(std::string(ip));

    dymicSwitchCurtain(true);

    if ((clientType != 1) && (mirrorVideoFormat_s != USBDISPLAY_VIDEO_FORMAT_H264))//非tail投屏
    {
        mirrorVideoFormat_s = USBDISPLAY_VIDEO_FORMAT_H264; //初始化配置，兼容客户端不设置格式情况

        VideoDecFormat decFormat;
        memset(&decFormat, 0, sizeof(VideoDecFormat));

        decFormat.type = videoEncH264;       

        setVideoDecFormat(&decFormat);
    }

    mirrorAVStart();

    HdmioutControl(1);//使能HDMIOUT

    return true;
}

bool ScreenMirrorStream::streamLeaveDel()
{
    HdmioutControl(0); //失能HDMIOUT

    WlanService::instance()->setMirrorIp("");

    mirrorAVStop();

    clearCommQueue();

    dymicSwitchCurtain(false);

    setShareScreenStatus(false);

    return true;
}


bool ScreenMirrorStream::setServerName(std::string name){
    std::lock_guard<std::mutex> lock(m_UserPwdLock);
    BZAirplayReceiverUpdateServerName(name.c_str());
    UsbDisplayUpdate(m_usbDisplayContext, name.c_str(), getdevicePassword().c_str(), USBDISPLAY_TRUE, USBDISPLAY_FALSE);
    m_deviceServerName = name;
    return true;
}


}

